import { renderingTasks } from './../common/index'
import { Sequence } from './reflection/Sequence'
import { ProjectItem } from './reflection/ProjectItem'
import { Project } from './reflection/Project'
import { existsSync } from 'fs-extra'
import {
  downloadFile,
  addEventListener,
  evalCommonMethod,
  getExtensionRootPath,
  loadJsxFile,
  methodEvaler,
  removeEventListener,
} from '../../core/common'
import { join } from 'path'
import { FileJson, Format, ImportOption } from '../../types/type.d'
import { isHttpPath } from '../../utils/utils'
import { HostType } from '../../constants/common'
import { getClipXml } from './fcpxml/index'

const _evalMethod = methodEvaler(HostType.pr)

/**
 * 初始化，初始化成功返回success, 所有pr下api需要在初始化后使用
 *
 * @export
 */
export async function init () {
  const extendRootPath = getExtensionRootPath()
  const jsxPath = join(extendRootPath, './jsx/pr')
  console.log('init jsx', jsxPath)
  await loadJsxFile(jsxPath)
  return _evalMethod('ping') // 检查是否初始化成功
}

/**
 *
 * 根据绝对路径打开一个文件
 * @export
 * @param  filePath
 * @return {*}
 */
export async function openFile (filePath: string) {
  if (!existsSync(filePath)) {
    return new Error('file no exist: ' + filePath)
  }
  // check can open or not
  const fileSuffix = filePath
    .substring(
      filePath.lastIndexOf('.') + 1,
      filePath.lastIndexOf('?') > -1 ? filePath.lastIndexOf('?') : undefined
    )
    .toLowerCase()
  switch (fileSuffix) {
    case 'prproj':
      const ret = await _evalMethod('openProject', filePath)
      console.log('open Project result', ret)
      const project = await getProject()
      return project
    case 'xml':
      return await _evalMethod('openFCPXML', filePath)
    default:
      return await _evalMethod('openFile', filePath)
  }
}

/**
 * 清理缓存
 *
 * @export
 * @return {*}
 */
export function clearCache () {
  return _evalMethod('clearCache')
}

/**
 * 关闭工程
 *
 * @export
 * @param 工程文件路径
 * @return {*}
 */
export function closeProject (filePath: string) {
  return _evalMethod('closeProject', filePath)
}

/**
 * 修改Project Bin中项目的文件路径
 *
 * @export
 * @param {string} key
 * @param {string} mediaPath
 * @return {*}
 */
export function changeMediaPath (key: string, mediaPath: string) {
  return existsSync(mediaPath) && _evalMethod('changeMediaPath', key, mediaPath)
}

/**
 * 修改Project Bin中项目的代理文件路径
 *
 * @export
 * @param {string} key
 * @param {string} mediaPath 文件路径|文件描述json string
 * @return {*}
 */
export function attachProxy (key: string, mediaPath: string) {
  return existsSync(mediaPath) && _evalMethod('attachProxy', key, mediaPath)
}

/**
 * 获取当前的project
 *
 * @export
 */
export async function getProject () {
  const project = await _evalMethod('getProject')
  return new Project(project)
}

/**
 * 获取当前的active sequence
 *
 * @export
 */
export async function getActiveSequence () {
  const sequence = await _evalMethod('getActiveSequence')
  return new Sequence(sequence)
}

/**
 * 引入单个文件
 * @param {string | FileJson} value
 * @returns {ProjectItem}
 */
export async function importFile (
  value: string | FileJson,
  options?: ImportOption
) {
  let filePath
  if (typeof value === 'string') {
    if (isHttpPath(value)) {
      filePath = await downloadFile(value, options?.tempFilePath)
    } else if (existsSync(value)) {
      filePath = value
    } else {
      throw new Error(`The file is not exist: ${value}`)
    }
  } else {
    // fake 处理
    filePath = ''
  }
  const projectItem = await _evalMethod('importFile', filePath)
  return new ProjectItem(projectItem)
}

/**
 * 唤醒ame, 准备JSON环境
 *
 */
function wakeAMEUp () {
  const extendRootPath = getExtensionRootPath()
  const jsonPath = join(extendRootPath, './jsx/index.jsx')
  const amePath = join(extendRootPath, './jsx/ame/index.jsx')
  evalCommonMethod('talkTo', {
    target: 'ame',
    body: `$.evalFile("${jsonPath}");`,
  })
  evalCommonMethod('talkTo', {
    target: 'ame',
    body: `$.evalFile("${amePath}");`,
  })
}


/**
 * 合成当前时间线
 * 
 * @export
 * @param {number} taskId
 * @param {string} outputPath
 * @param {string} presetPath
 * @return {*} 
 */
export async function render (
  taskId: number,
  outputPath: string,
  presetPath: string
) {
  const project = await getProject()
  if (!project) {
    return new Error('project not exist')
  }
  const activeSequece = await getActiveSequence()
  if (!activeSequece) {
    return new Error('active sequence not exist')
  }
  if (!existsSync(presetPath)) {
    return new Error('preset path not exist')
  }
  const jobId = await _evalMethod('render', { outputPath, presetPath })
  const task = {
    progress: 0,
    status: 'initial',
    taskId: taskId,
  }
  renderingTasks.set(jobId, task)
  return task
}

/**
 * 获取 AME 的格式和预设列表
 * @returns
 */
export function getAMEFormats (): Promise<Format[]> {
  return new Promise((resolve, reject) => {
    let id = -1
    const eventId = `com.sobey.adobe.event.get-formats-${Date.now()
      .toString()
      .slice(6)}`
    const handler = (e: any) => {
      e.data.forEach((i: any) => {
        i.presets = i.presets || []
        i.presets = i.presets.map((p: string) => {
          const arr = p.split('#')
          return {
            id: arr[0],
            name: arr[1],
          }
        })
      })
      resolve(e.data)
      clearTimeout(id)
    }
    addEventListener(eventId, handler, {
      once: true,
    })
    // 先唤醒ame
    wakeAMEUp()
    evalCommonMethod('talkTo', {
      target: 'ame',
      body: JSON.stringify({
        action: 'getFormats',
        type: eventId,
      }),
    })
    const timeout = 60 * 1000
    id = window.setTimeout(() => {
      removeEventListener(eventId, handler)
      reject(new Error('get AME formats timeout'))
    }, timeout)
  })
}
